#ifndef INCLUDE_MM_H_
#define INCLUDE_MM_H_
#include "type.h"
#include "queue.h"

#define PTE_C 2
#define PTE_D 1
#define PTE_V 1
#define PTE_G 1
#define PTE_S 1

#define TLB_NUM 64
//#define PAGE_FRAME_NUM 0x4000
#define PAGE_FRAME_NUM 0x10
#define PAGE_SIZE 0x1000
#define SD_MAX_ADDR 0xc200
#define BUFFER 0xffffffffa0400000
#define ODD_PAGE 0x0000000000001000
#define ENTRYHI_INVALID 0x000000ffffffe000

typedef struct page_frame
{
    uint64_t pfn; // fake_pfn
    PTE_t *vpte;
    uint64_t asid;
    uint64_t paddr; // physical address: used to fill entrylo
    int sd_card;
    struct page_frame *prev;
    struct page_frame *next;
    uint64_t key;
} page_frame_t;

extern page_frame_t page_frame[PAGE_FRAME_NUM];
page_frame_t *clock_ptr;

queue_t free_list;
queue_t busy_list;
int glob;

void get_TLB_info();
void init_TLB(void);
page_frame_t *page_alloc(void);
void page_frame_init(page_frame_t *item);

void physical_frame_initial(uint64_t start, uint64_t end);
void do_tlb_refill();
void do_tlb_invalid();

uint32_t rand_index();

void frame_exchange(page_frame_t *frame0, page_frame_t *frame1, page_frame_t *frame2, page_frame_t *frame3);

extern void tlb_exception_helper();
extern void tlb_modify_helper();

uint64_t do_shmget(uint64_t key);
uint64_t do_shmat(uint64_t shmid);
uint64_t do_shmdt(uint64_t addr);

#endif
